import java.util.PriorityQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.PriorityBlockingQueue;

public class Demo7 {
    static class MyTimerTesk implements Comparable<MyTimerTesk>{
        public Runnable task;
        public long Time;
        public MyTimerTesk(Runnable task,long Time){
            this.task = task;
            this.Time = System.currentTimeMillis() + Time;
        }
        public long getTime(){
            return Time;
        }
        public void run(){
            task.run();
        }
        //重写CompareTo方法
        @Override
        public int compareTo(MyTimerTesk o) {
            return (int)(this.Time - o.Time);
        }
    }
    static class MyTimer{
        Object locker = new Object();
        PriorityQueue<MyTimerTesk> queue = new PriorityQueue<>();
        public MyTimer(){
            //定时器内部就是创建线程执行任务
            Thread t = new Thread(()->{
                try {
                    while (true){
                        //加锁避免线程安全问题
                        synchronized (locker){
                            //读取队列中最早的元素
                            MyTimerTesk task = queue.peek();
                            //运用while循环是因为要再次确认task != null，防止被唤醒之后task == null
                            while (task == null){
                                    //此处等待是因为防止线程忙等，当task == null的时候，不至于一直循环
                                    locker.wait();
                                    task = queue.peek();
                            }
                            //获取当前系统时间
                            Long curtime = System.currentTimeMillis();
                            if (curtime > task.Time){
                                queue.poll();
                                task.run();

                            }else {
                                //此处等待也是为了避免忙等，
                                locker.wait(task.getTime() - curtime);
                            }
                        }
                    }
                }catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            });
            t.start();
        }
        public void Schedule(Runnable runnable,long time){
            synchronized (locker){
                MyTimerTesk task = new MyTimerTesk(runnable,time);
                queue.add(task);
                locker.notify();
            }
        }
    }

    public static void main(String[] args) {
        MyTimer timer = new MyTimer();
        timer.Schedule(()->{
            System.out.println("Hello 3000");
        },3000);
        timer.Schedule(()->{
            System.out.println("Hello 2000");
        },2000);
        timer.Schedule(()->{
            System.out.println("Hello 1000");
        },1000);
    }
}
